<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2020-9-28 10:55:00
// +----------------------------------------------------------------------

namespace buwang\util\alipay;

use Alipay\EasySDK\Kernel\Config;
use Alipay\EasySDK\Kernel\Factory;
use app\common\model\MemberPayment;
use buwang\exception\MiniappException;
use think\facade\Cache;

/**
 * 租户支付宝支付统一处理
 */
class AliPay
{
    public $payment;
    public function __construct($bw_member_app_id=0,$notifyUrl='/manage/recharge/ali_notify_page')
    {
        Factory::setOptions($this->getOptions($bw_member_app_id,$notifyUrl));
        $this->payment = Factory::payment();
    }


    /**
     * 设置配置
     * @return Config
     */
    protected function getOptions($bw_member_app_id,$notifyUr)
    {
        $options = new Config();
        $options->protocol = 'https';
        $options->gatewayHost = 'openapi.alipay.com';
        $options->signType = 'RSA2';

        //租户支付逻辑
        if ($bw_member_app_id) {
            //apiname为 wechat alipay
            $config = MemberPayment::getPayConfig($bw_member_app_id, 'alipay');
            if (!$config) {
                throw new MiniappException('请确认支付宝支付配置是否有问题！',0);
            }
            $options->appId = $config['app_id']??'';
            //应用私钥
            $options->merchantPrivateKey = $config['public_key']??'';
            //应用公钥证书路径
            $options->merchantCertPath = $config['alipay_cert_path']??'';
            //支付宝公钥证书路径
            $options->alipayCertPath = $config['alipay_public_path']??'';
        }else{
            //总平台的支付宝支付设置
            $config = bw_config('ali_pay');
            $options->appId = $config['ali_app_id'];
            //应用私钥
            $ali_merchant_private_key = $config['ali_merchant_private_key']??'';
            //应用公钥证书路径
            $ali_merchant_cert_path = $config['ali_merchant_cert_path']??'';
            //支付宝公钥证书路径
            $ali_cert_path = $config['ali_cert_path']??'';
            if(!$ali_merchant_private_key || !$ali_merchant_cert_path|| !$ali_cert_path){
                throw new MiniappException('请先完善平台支付宝支付配置！',0);
            }
            $options->merchantPrivateKey = $ali_merchant_private_key;
            $ali_merchant_cert_path = json_decode($ali_merchant_cert_path, true);
            $options->merchantCertPath = $ali_merchant_cert_path[0]['url']??'';
            $ali_cert_path = json_decode($ali_cert_path, true);
            $options->alipayCertPath = $ali_cert_path[0]['url']??'';
        }

        //支付宝根证书路径
        $options->alipayRootCertPath = root_path() . 'data' . DS . 'cert'. DS . 'alipayRootCert.crt';

        // 为避免私钥随源码泄露，推荐从文件中读取私钥字符串而不是写入源码中
        //$options->merchantPrivateKey = root_path() . 'runtime' . DS . 'merchantPrivateKey.txt';
        //注：如果采用非证书模式，则无需赋值上面的三个证书路径，改为赋值如下的支付宝公钥字符串即可
        //$options->alipayPublicKey = root_path() . 'runtime' . DS . 'alipayCertPublicKey_RSA2.crt';
        //可设置异步通知接收服务地址（可选）
        $options->notifyUrl = request()->domain().$notifyUr;
        //可设置AES密钥，调用AES加解密相关接口时需要（可选）
//        if ($this->config['encryptKey']) {
//            $options->encryptKey = $this->config['encryptKey'];
//        }
        return $options;
    }


    /**
     * 支付宝PC支付
     * @param $passback_params-附加参数-在回调时会返回
     * @param $subject-订单标题
     * @param $outTradeNo-商户订单号
     * @param $totalAmount-订单总金额，单位为元，精确到小数点后两位
     * @param $returnUrl-跳转地址
     */
    public function paymentPage($member_id,$passback_params, $subject, $outTradeNo, $totalAmount, $returnUrl='')
    {
        $result = $this->payment->page()->optional('passback_params', $passback_params)->pay($subject, $outTradeNo, $totalAmount, $returnUrl);
        if(isset($result->body)){
            //存储到redis，5分钟有效期
            Cache::store('redis')->set("zhifu_message_{$member_id}", $result->body, 300);

            $domain = request()->domain();
            return $domain.'/manage/member/recharge/page';
        }
        return '';
    }

    /**
     * 支付宝APP支付
     * @param $passback_params-附加参数-在回调时会返回
     * @param $subject-订单标题
     * @param $outTradeNo-商户订单号
     * @param $totalAmount-订单总金额，单位为元，精确到小数点后两位
     */
    public function paymentAPP($passback_params,$subject, $outTradeNo, $totalAmount)
    {
        $result = $this->payment->app()->optional('passback_params', $passback_params)->pay($subject, $outTradeNo, $totalAmount);
        return $result->body;
    }

    /**
     * 手机网页-H5支付
     * @param $passback_params -附加参数-在回调时会返回
     * @param $subject -订单标题
     * @param $outTradeNo -商户订单号
     * @param $totalAmount -订单总金额，单位为元，精确到小数点后两位
     * @param $quitUrl -同步跳转地址
     */
    public function paymentWap($passback_params,$subject, $outTradeNo, $totalAmount, $quitUrl='')
    {
        $result = $this->payment->wap()->optional('passback_params', $passback_params)->pay($subject, $outTradeNo, $totalAmount, $quitUrl, $quitUrl);
        return $result->body;
    }

    /**
     * 二维码支付-订单码支付
     * @param $passback_params-附加参数-在回调时会返回
     * @param $subject-订单标题
     * @param $outTradeNo-商户订单号
     * @param $totalAmount-订单总金额，单位为元，精确到小数点后两位
     */
    public function paymentFaceToFace($passback_params,$subject, $outTradeNo, $totalAmount)
    {
        $result = $this->payment->faceToFace()->optional('passback_params', $passback_params)->precreate($subject, $outTradeNo, $totalAmount);
        return isset($result->body) ? $result->body : $result;
    }

    /**
     * 支付宝回调验签
     * @param $data
     */
    public function alipayVerifyNotify($data)
    {
        $verify = $this->payment->common()->verifyNotify($data);
        if (false === $verify) {
            return false;
        }else{
            return true;
        }
    }

    /**
     * 统一收单交易退款接口
     * @param $outTradeNo:订单号
     * @param $refundAmount:退款金额
     * @param $outRequestNo:退款单号
     * @return mixed
     */
    public function refund($outTradeNo, $refundAmount, $outRequestNo)
    {
        return$this->payment->common()->optional('out_request_no', $outRequestNo)->refund($outTradeNo, $refundAmount);
    }

    /**
     * 统一收单交易查询
     * @param $orderSn:订单号
     */
    public function queryPay($orderSn)
    {
        return $this->payment->common()->query($orderSn);
    }

    /**
     * 统一收单交易退款查询
     * @param $outTradeNo:订单号
     * @param $outRequestNo:退款单号
     */
    public function queryRefund($outTradeNo, $outRequestNo)
    {
        return $this->payment->common()->queryRefund($outTradeNo, $outRequestNo);
    }
}